/**
 *
 */
package com.cmcc.awareness;

import java.util.ArrayList;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.pcap4j.packet.Packet;

/**
 * @Date 2018年4月11日 上午10:48:21
 * @author Amish
 * 
 * 对应proto.dat中的一个<START><END>，代表一个业务，其下可能有多个Protocol比如[TCP]或[UDP]
 * 
 * eg:
	<START>
	# 1865
	NAME:WeiXin_VoIP_Voice
	[UDP]
	# 10866
	{b|3|0x0a}{b|4|0x06}{b|5|0x08}{b|17|0x18}{b|18|0x01}{b|19|0x20}
	[UDP]
	# 23795
	{b|0|0xd0}{b|1|0x0a}{b|3|0x0a}{b|4|0x07}{b|5|0x08}{b|18|0x18}{b|19|0x00}{b|20|0x22}
	[UDP]
	# 27749
	{b|0|0xd5}{x|6|0x201003180010}{x|3|0x180122}
	#201712
	[UDP]
	{o|0|[0xa0,0xa1,0xa3]}{x|6|0x101018282228}
	[UDP]
	{b|0|0xd5}{x|6|0x021003180010}{x|3|0x180020}
	[UDP]
	{b|0|0xa3}{b|9|0xeb}{b|10|0x0e}{b|11|0x10}{b|12|0x20}{b|13|0x18}{b|-1|0x00}{b|-2|0x38}
	[UDP]
	{b|0|0xa1}{b|5|0xeb}{b|6|0x0e}{b|7|0x10}{b|8|0x20}{b|9|0x18}{b|-1|0x00}{b|-2|0x38}
	[UDP]
	{b|0|0xd6}{b|9|0x08}{b|13|0xea}{b|14|0xa5}{b|15|0x81}{b|16|0xf5}{b|17|0x85}
	<END>
 */
public class ProtoDatApp {
	private static Logger logger = LogManager.getLogger(ProtoDatApp.class);
	
	public String appName;//对应proto.list中的业子项名称，如QIYI_Browsing、WeiXin_VoIP_Voice
	public ArrayList<ProtoDatProtocolFeatureCode> protocolFeatures; //每个[UDP]/[TCP]对应List中的一个
	
	public ProtoDatApp(){
		this.protocolFeatures = new ArrayList<ProtoDatProtocolFeatureCode> ();
	}
	
	public String distinguish(String protocolType,jpcap.packet.Packet packet){
		//System.out.println("\n distinguish procedure : "+appName);
		for(ProtoDatProtocolFeatureCode protoDatProtocolFeatureCode : protocolFeatures){
			
			if(protoDatProtocolFeatureCode.distinguish(protocolType, packet)){
				return this.appName;
			}
		}
		return null;
	}
	
	public ProtoDatProtocolFeatureCode distinguishWithRule(String protocolType,Packet packet){
		//System.out.println("\n distinguish procedure : "+appName);
		for(ProtoDatProtocolFeatureCode protoDatProtocolFeatureCode : protocolFeatures){
			
			if(protoDatProtocolFeatureCode.distinguish(protocolType, packet)){
				return protoDatProtocolFeatureCode;
			}
		}
		return null;
	}
	
	public String distinguish(String protocolType,Packet packet){
		//System.out.println("\n distinguish procedure : "+appName);
		for(ProtoDatProtocolFeatureCode protoDatProtocolFeatureCode : protocolFeatures){
			
			if(protoDatProtocolFeatureCode.distinguish(protocolType, packet)){
				return this.appName;
			}
		}
		return null;
	}
	
	/**
	 * 
	 * @param alTemp
	 */
	public void parseProtoDatApp(ArrayList<String> alTemp){
		ArrayList<String> alTempSub = new ArrayList<String>();
		ProtoDatProtocolFeatureCode protoDatProtocolFeatureCode = null;
		for(String str : alTemp){
			if(str.startsWith("<START>")){
				//do nothing
			}else if(str.startsWith("NAME:")){
				this.appName = str.substring(5);
				
			}else if(str.startsWith("#")){
				//do nothing
			}else if(str.startsWith("[")){
				if(protoDatProtocolFeatureCode == null){//遇到第一个协议标识
					protoDatProtocolFeatureCode = new ProtoDatProtocolFeatureCode(this.appName);
					protoDatProtocolFeatureCode.protocolType = str.substring(1,str.indexOf("]"));
					//System.out.println(protoDatProtocolFetureCode.protocolType);
				}else{//遇到下一个协议标识,先将之前的内容解析
					
					protoDatProtocolFeatureCode.parseProtoDatProtocolFetureCode(alTempSub);
					protocolFeatures.add(protoDatProtocolFeatureCode);
					alTempSub.clear();
					
					protoDatProtocolFeatureCode = new ProtoDatProtocolFeatureCode(this.appName);
					protoDatProtocolFeatureCode.protocolType = str.substring(1,str.indexOf("]"));
					//System.out.println(protoDatProtocolFetureCode.protocolType);
				}
				
			}else if(str.startsWith("<END>")){//遇到APP结尾
				
				//解析最后一个Protocol Feture Code
				if(protoDatProtocolFeatureCode != null){//<START>和<END>之间为null或者都是##或者没有[ ]时此处会为null
					protoDatProtocolFeatureCode.parseProtoDatProtocolFetureCode(alTempSub);
					protocolFeatures.add(protoDatProtocolFeatureCode);
				}
				alTempSub.clear();
			}else{
				alTempSub.add(str);
			}
		}
	}
	
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("NAME:"+this.appName+"\n");
		for(ProtoDatProtocolFeatureCode protoDatProtocolFeatureCode : protocolFeatures ){
			sb.append(protoDatProtocolFeatureCode.toString());	
		}
		return sb.toString();
	}

}
